// 数据库配置的读写支持
package xgodbconfig

import (
	"sync"

	"gorm.io/gorm"
)

// 数据库相关配置
type Config struct {
	DB                  *gorm.DB
	ConfigTable         string                         // 配置表名称
	ConfigUserTable     string                         // 用户配置存储表
	ConfigureGroupTable string                         // 配置项分组表表明
	Lock                sync.Mutex                     // 缓存锁
	Cache               map[string]Configure           // 缓存配置项
	CacheUser           map[uint]string                // 用户配置项
	ConfigEdit          func(name string) error        // 配置项修改的回调函数
	listen              map[string][]func(name string) // 配置项变动后的监听回调
}

// 默认配置表所在的配置
var _default Config = Config{
	ConfigTable:         "configure",
	ConfigUserTable:     "configure_user",
	ConfigureGroupTable: "configure_group",
	Lock:                sync.Mutex{},
	CacheUser:           map[uint]string{},
}

// 注入配置项
func Regedit(c *Config) {
	if c != nil {
		if _default.DB == nil && c.DB != nil {
			_default.DB = c.DB
		}
		if c.ConfigTable != "" {
			_default.ConfigTable = c.ConfigTable
		}
		if c.ConfigUserTable != "" {
			_default.ConfigUserTable = c.ConfigUserTable
		}
		if c.ConfigureGroupTable != "" {
			_default.ConfigureGroupTable = c.ConfigureGroupTable
		}
		if c.ConfigEdit != nil {
			_default.ConfigEdit = c.ConfigEdit
		}
		// 生成默认配置表
		_default.DB.AutoMigrate(&Configure{}, &ConfigureUser{}, &ConfigureGroup{})
	}
}

// 配置项信息存储表
type Configure struct {
	Id          uint    `gorm:"column:id;primaryKey;type:INT UNSIGNED;not null;autoIncrement" json:"id" form:"id"`
	NameKey     string  `gorm:"column:name_key;type:varchar(100);unique;comment:配置项key" json:"name_key" form:"name_key"`                                       //配置项key
	NameCn      string  `gorm:"column:name_cn;type:varchar(200);comment:配置项名称" json:"name_cn" form:"name_cn"`                                                  //配置项名称
	NameGroup   string  `gorm:"column:name_group;type:varchar(100);index;comment:配置项组" json:"name_group" form:"name_group"`                                    //配置项组
	Types       string  `gorm:"column:types;type:varchar(20);index;comment:配置项类型" json:"types" form:"types"`                                                   //配置项类型
	Desc        string  `gorm:"column:desc;type:text;comment:配置项介绍信息" json:"desc" form:"desc"`                                                                 //配置项介绍信息
	ValueBool   uint8   `gorm:"column:value_bool;type:tinyint unsigned;default:0;comment:bool类型的值存储 0-False 1-True" json:"value_bool" form:"value_bool"`       // bool类型的值存储 uint8
	ValueString string  `gorm:"column:value_string;type:text;comment:字符串类型配置" json:"value_string" form:"value_string"`                                         // 字符串类型配置
	ValueInt    int64   `gorm:"column:value_int;type:bigint;default:0;comment:int类型配置" json:"value_int" form:"value_int"`                                      // int类型配置
	ValueFloat  float64 `gorm:"column:value_float;type:double;default:0;comment:float类型配置" json:"value_float" form:"value_float"`                              // float类型配置
	EnumSelect  string  `gorm:"column:enum_select;type:text;comment:下拉列表，多项使用,分割key和key_cn使用:分割，下拉选择的值存储在value_string中" json:"enum_select" form:"enum_select"` //下拉列表，多项使用,分割key和key_cn使用:分割，下拉选择的值存储在value_string中
	CreatedAt   string  `gorm:"column:created_at;type:datetime;comment:创建时间" json:"created_at" form:"created_at"`                                              //创建时间
	UpdatedAt   string  `gorm:"column:updated_at;type:datetime;comment:更新时间" json:"updated_at" form:"updated_at"`                                              //更新时间
}

// 表名
func (c *Configure) TableName() string {
	return _default.ConfigTable
}

// 用户个性化配置项存储表
type ConfigureUser struct {
	UserId    uint   `gorm:"column:user_id;primaryKey;type:INT UNSIGNED;comment:用户ID" json:"user_id" form:"user_id"` //用户ID
	Configure string `gorm:"column:configure;type:longtext;comment:配置信息JSON串" json:"configure" form:"configure"`     //配置信息JSON串
}

func (c *ConfigureUser) TableName() string {
	return _default.ConfigUserTable
}

// 配置项分组信息
type ConfigureGroup struct {
	Id          uint   `gorm:"column:id;primary_key;NOT NULL" json:"id" form:"id"`                                         // 自增ID
	Fid         uint   `gorm:"column:fid;default:0;NOT NULL;comment:'上级分组ID'" json:"fid" form:"fid"`                       // 上级分组ID
	NameGroup   string `gorm:"column:name_group;NOT NULL;comment:'分组名_key值'" json:"name_group" form:"name_group"`          // 分组KEY下标
	NameGroupCn string `gorm:"column:name_group_cn;NOT NULL;comment:'分组值-中文名称'" json:"name_group_cn" form:"name_group_cn"` // 分组名称
}

func (c *ConfigureGroup) TableName() string {
	return _default.ConfigureGroupTable
}

// 配置项修改函数，用于调用外部的修改后触发操作
//
//	name	修改的配置项名称
func configEdit(name string) {
	// 检测修改的name是否为配置项的几个
	switch name {
	case "FRAM_SYNC_URL", "FRAM_SYNC_URL_AES", "FRAM_SYNC_DOMAIN", "FRAM_SYNC_DOMAIN_AES":
		return
	}
	if _default.ConfigEdit != nil {
		go _default.ConfigEdit(name)
	}
	// 进行函数回调
	if f, ok := _default.listen[name]; ok {
		for i := 0; i < len(f); i++ {
			go f[i](name)
		}
	}
}

// 追加变量变更通知函数
//
//	name	监听的配置项名称
//	fun		执行的回调名称
func Listen(name string, fun func(n string)) {
	if fun == nil {
		return
	}
	if _default.listen == nil {
		_default.listen = map[string][]func(name string){}
	}
	if _, ok := _default.listen[name]; !ok {
		_default.listen[name] = []func(n string){}
	}
	_default.listen[name] = append(_default.listen[name], fun)
}

// 追加变量变更通知函数-多变量添加
//
//	name	监听配置项名称
//	fun		执行回调的名称
func Listens(name []string, fun func(n string)) {
	for i := 0; i < len(name); i++ {
		Listen(name[i], fun)
	}
}
